import * as React from 'react';
import * as shallowEqual from 'shallowequal';
import _ from './lodash';

// 如果有reactjs 控件的话，必须用tsx结尾

/**
 * 控件参数接口定义
 */
interface ComponentProps {};
/**
 * 控件状态接口定义
 */
interface ComponentStates {};


/**
 * 把stateless component转换成stateful component
 * @param wrappedFunction
 */
export function stateful<T>(wrappedStateless: (props: T) => any) {
  /**
   * 内部转换类
   */
  class StatefulComponent extends React.Component<T, T>{
    /**
     * 构造函数
     * @param props
     * @param context
     */
    constructor(props, context) {
      super(props, context);
    }

    /**
     * 加载的时候把props更新到states里面
     */
    componentWillMount() {
      this.setState(_.assign(this.state)(this.props));
    }

    /**
     * 触发状态变更的时候把props更新到states里面
     * @param nextProps
     */
    componentWillReceiveProps(nextProps: T) {
      this.setState(_.assign(this.state)(nextProps));
    }

    /**
     * 渲染方法
     */
    render() {
      //
      return wrappedStateless(this.state)
    }
  }
  return StatefulComponent;
}

/**
 * 给component加上pure控制(单纯组件，只有参数不一样的时候才重新渲染)
 * @param WrappedComponent
 */
export function pure(WrappedComponent: any) {
  class PureComponent extends React.Component<ComponentProps, ComponentStates> {
    /**
     * 构造函数
     * @param props
     * @param context
     */
    constructor(props, context) {
      super(props, context);
    }

    /**
     * 参数变更控制
     * @param nextProps
     */
    shouldComponentUpdate(nextProps: ComponentProps) {
      // 砍掉func
      const filteredNextProps = _.omit(_.functions(nextProps))(nextProps);
      const filteredProps = _.omit(_.functions(this.props))(this.props);
      return !shallowEqual(filteredProps, filteredNextProps)
    }

    /**
     * 渲染函数
     */
    render() {
      return (
        <WrappedComponent {...this.props}/>
      );
    }
  }
   return PureComponent
}

